package com.lap.framework.tools;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.lap.framework.exception.JsonParserException;

/**
 * Json 工具类，建议使用工具类，不要自己创建对象
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
public final class JsonUtil {
  private static final ObjectMapper MAPPER = new ObjectMapper();

  static {
    MAPPER.registerModule(new JavaTimeModule()); // jdk8时间注册
    MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 禁止jdk8时间问题
    MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // 对于空对象转json的时候不抛错误
    MAPPER.disable(
        DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // 设置输入时忽略在json字符串中存在但在java对象实际没有的属性
    MAPPER.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // 允许属性名称没有引号
    MAPPER.configure(Feature.ALLOW_SINGLE_QUOTES, true); // 允许单引号
    MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 设置输出时包含属性的风格
  }

  private JsonUtil() {}

  /**
   * 类型转换
   *
   * @param <T> 类型
   * @param object 对象入参
   * @return 返回类型
   */
  public static <T> T convert(Object object) {
    try {
      return MAPPER.convertValue(object, new TypeReference<>() {});
    } catch (IllegalArgumentException e) {
      throw new JsonParserException(e);
    }
  }

  /**
   * json 转换到对象
   *
   * @param <T> 类型
   * @param json 字符JSON
   * @param clazz 类型
   * @return 返回对象
   */
  public static <T> T toObject(String json, Class<T> clazz) {
    try {
      return MAPPER.readValue(json, clazz);
    } catch (JsonProcessingException e) {
      throw new JsonParserException(e);
    }
  }

  /**
   * json 转换引用类型
   *
   * @param json 字符json
   * @param typeReference 类型
   * @param <T> 类型
   * @return 返回对象
   */
  public static <T> T toObject(String json, TypeReference<T> typeReference) {
    try {
      return MAPPER.readValue(json, typeReference);
    } catch (JsonProcessingException e) {
      throw new JsonParserException(e);
    }
  }

  /**
   * 对象转换到json
   *
   * @param object 对象
   * @return 字符串
   */
  public static String toJson(Object object) {
    try {
      return MAPPER.writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw new JsonParserException(e);
    }
  }

  /**
   * 对象转换成bytes
   *
   * @param object 对象
   * @return 返回字节
   */
  public static byte[] toBytes(Object object) {
    try {
      return MAPPER.writeValueAsBytes(object);
    } catch (JsonProcessingException e) {
      throw new JsonParserException(e);
    }
  }

  /**
   * 提供美化输出，使用场景主要是调试使用，非特殊需求，请勿这样获取字符串
   *
   * @param object 对象
   * @return 美化字符串
   */
  public static String prettyOut(Object object) {
    try {
      return MAPPER
          .writerWithDefaultPrettyPrinter()
          .withDefaultPrettyPrinter()
          .writeValueAsString(object);
    } catch (JsonProcessingException e) {
      throw new JsonParserException(e);
    }
  }
}
